package com.xuzimian.globaldemo.spring.core.ioc.context;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Spring Ioc 容器Context类，主要为分析refresh() 方法，而覆盖了继承的refresh 方法，
 * 实际并未改变refresh 代码功能，只是添加了注释。
 *
 * @program: global-demo
 * @description:
 * @author: xzm
 * @create: 2019-05-15 16:51
 **/
public class MyClassPathXmlApplicationContxt extends ClassPathXmlApplicationContext {

    private final Object startupShutdownMonitor = new Object();

    /**
     *
     * @throws BeansException
     * @throws IllegalStateException
     */
    @Override
    public void refresh() throws BeansException, IllegalStateException {

        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            //这里是在子类中启动refreshBeanFactory()的地方
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // 设置BeanFactory的后置处理
                postProcessBeanFactory(beanFactory);

                // 调用BeanFactory的后处理器，这些后处理器是在Bean定义中向容器注册的。
                invokeBeanFactoryPostProcessors(beanFactory);

                // 注册Bean的后处理器，在Bean创建过程中调用。.
                registerBeanPostProcessors(beanFactory);

                // 对上下文中的消息源进行初始化
                initMessageSource();

                // 初始化上下文中的事件机制
                initApplicationEventMulticaster();

                // 初始化其他的特殊Bean
                onRefresh();

                // 检查监听Bean,并且将这些监听器Bean向容器注册
                registerListeners();

                // 实例化所有的(non-lazy-init) 单例
                finishBeanFactoryInitialization(beanFactory);

                // 发布容器事件，结束refresh过程
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
                // 为防止Bean资源占用，在异常处理中，销毁已经在前面过程中生成的单例Bean
                destroyBeans();
                // 重置'active'标志
                cancelRefresh(ex);
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }
}
